Bug 596428 - GtkAssistant: Support ending with a progress page
authorMatthew Barnes <mbarnes@redhat.com>
Wed, 2 Jun 2010 20:00:16 +0000 (16:00 -0400)
committerMatthew Barnes <mbarnes@redhat.com>
Thu, 3 Jun 2010 21:03:14 +0000 (17:03 -0400)
- Add gtk_assistant_commit()

  This function discards the visited pages list so the back button is not
  shown on the current page, and removes the cancel button from subsequent
  pages.  Use this when information provided thus far cannot be revisited.

- Don't show the Forward button on a GTK_ASSISTANT_PAGE_PROGRESS if it's
  the last page (according to the forward page function).

- Append a progress page to the GtkAssistant demo.

demos/gtk-demo/assistant.c
docs/reference/gtk/gtk3-sections.txt
gtk/gtk.symbols
gtk/gtkassistant.c
gtk/gtkassistant.h

index 6cb5399f6baa1dda5026c04886e10eca3c54e7fe..a00c595370232f84107e630b07d014a4968aa0ce 100644 (file)
@@ -9,12 +9,35 @@
 #include "demo-common.h"
 
 static GtkWidget *assistant = NULL;
+static GtkWidget *progress_bar = NULL;
+
+static gboolean
+apply_changes_gradually (gpointer data)
+{
+  gdouble fraction;
+
+  /* Work, work, work... */
+  fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress_bar));
+  fraction += 0.05;
+
+  if (fraction < 1.0)
+    {
+      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress_bar), fraction);
+      return TRUE;
+    }
+  else
+    {
+      /* Close automatically once changes are fully applied. */
+      gtk_widget_destroy (assistant);
+      return FALSE;
+    }
+}
 
 static void
 on_assistant_apply (GtkWidget *widget, gpointer data)
 {
-  /* Apply here changes, this is a fictional
-     example, so we just do nothing here */
+  /* Start a timer to simulate changes taking a few seconds to apply. */
+  g_timeout_add (100, apply_changes_gradually, NULL);
 }
 
 static void
@@ -38,6 +61,13 @@ on_assistant_prepare (GtkWidget *widget, GtkWidget *page, gpointer data)
   title = g_strdup_printf ("Sample assistant (%d of %d)", current_page + 1, n_pages);
   gtk_window_set_title (GTK_WINDOW (widget), title);
   g_free (title);
+
+  /* The fourth page (counting from zero) is the progress page.  The
+  * user clicked Apply to get here so we tell the assistant to commit,
+  * which means the changes up to this point are permanent and cannot
+  * be cancelled or revisited. */
+  if (current_page == 3)
+      gtk_assistant_commit (GTK_ASSISTANT (widget));
 }
 
 static void
@@ -127,6 +157,26 @@ create_page3 (GtkWidget *assistant)
   g_object_unref (pixbuf);
 }
 
+static void
+create_page4 (GtkWidget *assistant)
+{
+  GtkWidget *page;
+
+  page = gtk_alignment_new (0.5, 0.5, 0.5, 0.0);
+
+  progress_bar = gtk_progress_bar_new ();
+  gtk_container_add (GTK_CONTAINER (page), progress_bar);
+
+  gtk_widget_show_all (page);
+  gtk_assistant_append_page (GTK_ASSISTANT (assistant), page);
+  gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), page, GTK_ASSISTANT_PAGE_PROGRESS);
+  gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), page, "Applying changes");
+
+  /* This prevents the assistant window from being
+   * closed while we're "busy" applying changes. */
+  gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), page, FALSE);
+}
+
 GtkWidget*
 do_assistant (GtkWidget *do_widget)
 {
@@ -142,6 +192,7 @@ do_assistant (GtkWidget *do_widget)
       create_page1 (assistant);
       create_page2 (assistant);
       create_page3 (assistant);
+      create_page4 (assistant);
 
       g_signal_connect (G_OBJECT (assistant), "cancel",
                        G_CALLBACK (on_assistant_close_cancel), &assistant);
index 3c1c8f748432ed85994317c5df3c76cec783a0a3..c156c1b3de04a00e60dc593a5209ea4e19d6866c 100644 (file)
@@ -367,6 +367,7 @@ gtk_assistant_get_page_complete
 gtk_assistant_add_action_widget
 gtk_assistant_remove_action_widget
 gtk_assistant_update_buttons_state
+gtk_assistant_commit
 
 <SUBSECTION Standard>
 GtkAssistantClass
index 367ca90e797a84049e4b0c26067d387be1218fd8..03b815a83bac7ed8b45a1a6ddcb9872ff5752ffc 100644 (file)
@@ -283,6 +283,7 @@ gtk_assistant_get_page_complete
 gtk_assistant_add_action_widget
 gtk_assistant_remove_action_widget
 gtk_assistant_update_buttons_state
+gtk_assistant_commit
 #endif
 #endif
 
index 97caaa0ad715ba8f8b0fea915b3ad5d094bfe328..3c18378cefc47cf1eab71b7bc9252e897ae70cca 100644 (file)
@@ -103,6 +103,8 @@ struct _GtkAssistantPrivate
   GtkAssistantPageFunc forward_function;
   gpointer forward_function_data;
   GDestroyNotify forward_data_destroy;
+
+  guint committed : 1;
 };
 
 static void     gtk_assistant_class_init         (GtkAssistantClass *class);
@@ -267,7 +269,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
    *
    * A handler for the ::apply signal should carry out the actions for which
    * the wizard has collected data. If the action takes a long time to complete,
-   * you might consider to put a page of type %GTK_ASSISTANT_PAGE_PROGRESS
+   * you might consider putting a page of type %GTK_ASSISTANT_PAGE_PROGRESS
    * after the confirmation page and handle this operation within the
    * #GtkAssistant::prepare signal of the progress page.
    *
@@ -472,6 +474,23 @@ compute_last_button_state (GtkAssistant *assistant)
     gtk_widget_hide (assistant->last);
 }
 
+static void
+compute_progress_state (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  gint page_num, n_pages;
+
+  n_pages = gtk_assistant_get_n_pages (assistant);
+  page_num = gtk_assistant_get_current_page (assistant);
+
+  page_num = (priv->forward_function) (page_num, priv->forward_function_data);
+
+  if (page_num >= 0 && page_num < n_pages)
+    gtk_widget_show (assistant->forward);
+  else
+    gtk_widget_hide (assistant->forward);
+}
+
 static void
 set_assistant_header_image (GtkAssistant *assistant)
 {
@@ -509,7 +528,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->cancel, TRUE);
       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
       gtk_widget_grab_default (assistant->forward);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->forward);
       gtk_widget_hide (assistant->back);
       gtk_widget_hide (assistant->apply);
@@ -521,7 +539,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->back, TRUE);
       gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
       gtk_widget_grab_default (assistant->apply);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->back);
       gtk_widget_show (assistant->apply);
       gtk_widget_hide (assistant->forward);
@@ -533,7 +550,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->back, TRUE);
       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
       gtk_widget_grab_default (assistant->forward);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->back);
       gtk_widget_show (assistant->forward);
       gtk_widget_hide (assistant->apply);
@@ -544,7 +560,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->close, priv->current_page->complete);
       gtk_widget_grab_default (assistant->close);
       gtk_widget_show (assistant->close);
-      gtk_widget_hide (assistant->cancel);
       gtk_widget_hide (assistant->back);
       gtk_widget_hide (assistant->forward);
       gtk_widget_hide (assistant->apply);
@@ -555,17 +570,23 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
       gtk_widget_grab_default (assistant->forward);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->back);
-      gtk_widget_show (assistant->forward);
       gtk_widget_hide (assistant->apply);
       gtk_widget_hide (assistant->close);
       gtk_widget_hide (assistant->last);
+      compute_progress_state (assistant);
       break;
     default:
       g_assert_not_reached ();
     }
 
+  if (priv->committed)
+    gtk_widget_hide (assistant->cancel);
+  else if (priv->current_page->type == GTK_ASSISTANT_PAGE_SUMMARY)
+    gtk_widget_hide (assistant->cancel);
+  else
+    gtk_widget_show (assistant->cancel);
+
   /* this is quite general, we don't want to
    * go back if it's the first page */
   if (!priv->visited_pages)
@@ -2264,6 +2285,35 @@ gtk_assistant_update_buttons_state (GtkAssistant *assistant)
   set_assistant_buttons_state (assistant);
 }
 
+/**
+ * gtk_assistant_commit:
+ * @assistant: a #GtkAssistant
+ *
+ * Erases the visited page history so the back button is not
+ * shown on the current page, and removes the cancel button
+ * from subsequent pages.
+ *
+ * Use this when the information provided up to the current
+ * page is hereafter deemed permanent and cannot be modified
+ * or undone.  For example, showing a progress page to track
+ * a long-running, unreversible operation after the user has
+ * clicked apply on a confirmation page.
+ *
+ * Since: 2.22
+ **/
+void
+gtk_assistant_commit (GtkAssistant *assistant)
+{
+  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+  g_slist_free (assistant->priv->visited_pages);
+  assistant->priv->visited_pages = NULL;
+
+  assistant->priv->committed = TRUE;
+
+  set_assistant_buttons_state (assistant);
+}
+
 
 
 /* accessible implementation */
index 47fd16ba866d506a5c7f1ce9313e9a6a0b69f538..8b7297fa7f910686a07eb973b9ad86262f2bb55a 100644 (file)
@@ -57,7 +57,8 @@ G_BEGIN_DECLS
  * used to handle buttons sensitivity and visibility.
  *
  * Note that an assistant needs to end its page flow with a page of type
- * %GTK_ASSISTANT_PAGE_CONFIRM or %GTK_ASSISTANT_PAGE_SUMMARY to be correct.
+ * %GTK_ASSISTANT_PAGE_CONFIRM, %GTK_ASSISTANT_PAGE_SUMMARY or
+ * %GTK_ASSISTANT_PAGE_PROGRESS to be correct.
  */
 typedef enum
 {
@@ -168,6 +169,7 @@ void                  gtk_assistant_remove_action_widget  (GtkAssistant
                                                           GtkWidget            *child);
 
 void                  gtk_assistant_update_buttons_state  (GtkAssistant *assistant);
+void                  gtk_assistant_commit                (GtkAssistant *assistant);
 
 G_END_DECLS